package com.cizzy.favorite.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.BooleanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.cizzy.favorite.feign.UserFeign;
import com.cizzy.favorite.feign.VideoFeign;
import com.cizzy.favorite.common.Result;
import com.cizzy.favorite.common.UserIdHolder;
import com.cizzy.favorite.entity.Favorite;
import com.cizzy.favorite.entity.dto.VideoDTO;
import com.cizzy.favorite.entity.vo.FavoriteRequest;
import com.cizzy.favorite.mapper.FavoriteMapper;
import com.cizzy.favorite.service.IFavoriteService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.seata.spring.annotation.GlobalTransactional;
import jakarta.annotation.Resource;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;

import java.util.List;

import static com.cizzy.favorite.config.CizzyFinal.FAVORITE_LOCK;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author crissy-月下闲人
 * @since 2023-11-02
 */
@Service
public class FavoriteServiceImpl extends ServiceImpl<FavoriteMapper, Favorite> implements IFavoriteService {

    @Resource
    private VideoFeign videoFeign;

    @Resource
    private UserFeign userFeign;

    @Resource
    private FavoriteMapper favoriteMapper;

    @Resource
    private RedissonClient redissonClient;

    @GlobalTransactional
    @Override
    public synchronized Result<Favorite> createFavorite(FavoriteRequest favoriteRequest) {
        RLock lock = redissonClient.getLock(FAVORITE_LOCK);
        lock.lock();
        Long userId = favoriteRequest.getUserId();
        Long videoId = favoriteRequest.getVideoId();
        if(userId == null || videoId == null) {
            return Result.error("请求参数错误");
        }
        QueryWrapper<Favorite> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id", userId).eq("video_id", videoId);
        boolean exist = favoriteMapper.exists(wrapper);
        Favorite favorite = new Favorite(userId, videoId);
        if (BooleanUtil.isFalse(exist)) {
            favoriteMapper.insert(favorite);
            userFeign.addUserCountById("favorite_count", userId, 1);
            videoFeign.addVideoCountById("favorite_count", videoId, 1);
        }
        lock.unlock();
        if(BooleanUtil.isTrue(exist)) {
            return Result.error("喜欢失败");
        } else {
            return Result.success(favorite);
        }
    }

    @GlobalTransactional
    @Override
    public Result<Favorite> cancelFavorite(FavoriteRequest favoriteRequest) {
        RLock lock = redissonClient.getLock(FAVORITE_LOCK);
        lock.lock();
        Long userId = favoriteRequest.getUserId();
        Long videoId = favoriteRequest.getVideoId();
        if(userId == null || videoId == null) {
            return Result.error("请求参数错误");
        }
        QueryWrapper<Favorite> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", userId).eq("video_id", videoId);
        boolean exist = favoriteMapper.exists(queryWrapper);
        Favorite favorite = new Favorite(userId, videoId);
        if (BooleanUtil.isTrue(exist)) {
            favoriteMapper.delete(queryWrapper);
            userFeign.addUserCountById("favorite_count", userId, -1);
            videoFeign.addVideoCountById("favorite_count", videoId, -1);
        }
        lock.unlock();
        if(BooleanUtil.isFalse(exist)) {
            return Result.error("取消喜欢失败");
        } else {
            return Result.success(favorite);
        }
    }

    @Override
    public Result<Boolean> isFavorited(Long userId, Long videoId) {
        if(userId == null || videoId == null) {
            return Result.error("请求参数错误");
        }
        QueryWrapper<Favorite> queryWrapper = new QueryWrapper<Favorite>().
                eq("user_id", userId).eq("video_id", videoId);
        return Result.success(BooleanUtil.isTrue(favoriteMapper.exists(queryWrapper)));
    }

    @Override
    public Result<List<VideoDTO>> getFavoriteById(Long userId) {
        if(userId == null) {
            return Result.error("请求参数错误");
        }
        QueryWrapper<Favorite> queryWrapper = new QueryWrapper<Favorite>().eq("user_id", userId);
        List<Favorite> favoriteList = favoriteMapper.selectList(queryWrapper);
        if(favoriteList == null) {
            return Result.error("喜欢列表查询失败");
        }
        List<Long> videoIdList = favoriteList.stream().map(Favorite::getVideoId).toList();
        List<VideoDTO> videoDTOList = videoFeign.getVideoListByIds(videoIdList).getData();
        if(videoDTOList == null) {
            return Result.error("喜欢列表查询失败");
        }
        return Result.success(videoDTOList);
    }

    @Override
    public Result<List<VideoDTO>> getFavoritePageById(Long userId, Integer page, Integer pageSize) {
        if(userId == null) {
            return Result.error("请求参数错误");
        }
        QueryWrapper<Favorite> queryWrapper = new QueryWrapper<Favorite>().
                eq("user_id", userId).last(String.format("LIMIT %d,%d", (page-1) * pageSize,page * pageSize));
        List<Favorite> favoriteList = favoriteMapper.selectList(queryWrapper);
        if(favoriteList == null) {
            return Result.error("喜欢列表查询失败");
        }
        List<Long> videoIdList = favoriteList.stream().map(Favorite::getVideoId).toList();
        List<VideoDTO> videoDTOList = videoFeign.getVideoListByIds(videoIdList).getData();
        if(videoDTOList == null) {
            return Result.error("喜欢列表查询失败");
        }
        return Result.success(videoDTOList);
    }

    @Override
    synchronized public Result<String> toLike(Long videoId) {
        Long userId = UserIdHolder.getUserId();
        QueryWrapper<Favorite> favoriteQueryWrapper = new QueryWrapper<>();
        favoriteQueryWrapper.eq("user_id", userId).eq("video_id", videoId);
        //TODO 判断该视频是否已经点赞
        boolean exist = favoriteMapper.exists(favoriteQueryWrapper);
        if (BooleanUtil.isFalse(exist)) {
            favoriteMapper.insert(new Favorite(userId, videoId));
            //TODO 远程调用视频微服务

            return Result.success("点赞成功", null);
        } else {
            favoriteMapper.delete(favoriteQueryWrapper);
            //TODO 远程调用视频微服务

            return Result.success("取消点赞成功", null);
        }
    }

    @Override
    public Result<List<VideoDTO>> getFavList() {
        Long userId = UserIdHolder.getUserId();
        //TODO 查询用户点赞视频的视频ID 集合
        List<Long> list = favoriteMapper.selectFavList(userId);
        if (CollectionUtil.isNotEmpty(list)) {
            //TODO 前往视频模块获取视频数据
            return videoFeign.getVideoListByIds(list);
        }
        return Result.success(null);
    }
}
